
 package ru.sbt.abyss.coordinator.web.security.mvc.filter.auth;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.io.IOException;
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpHeaders;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.web.util.WebUtils;
 import ru.sbt.abyss.coordinator.core.jwt.JwtEncoder;
 import ru.sbt.abyss.coordinator.validation.XssValidator;
 
 public class TokenAuthFilter extends AbstractAuthenticationProcessingFilter {
 
   private static final Logger LOG = LoggerFactory.getLogger(TokenAuthFilter.class);
   public static final String USER_CONTEXT_KEY = "USER_AUTH_DATA";
   private static final String BEARER_PREFIX = "Bearer";
 
   private final String cookieName;
   private final String jwtEncodingKey;
   private final boolean isXssValidationEnabled;
 
   private static final ObjectMapper mapper = new ObjectMapper();
 
   public TokenAuthFilter(
       final RequestMatcher requestMatcher,
       String cookieName,
       String jwtEncodingKey,
       boolean isXssValidationEnabled) {
 
     super(requestMatcher);
     this.cookieName = cookieName;
     this.jwtEncodingKey = jwtEncodingKey;
     this.isXssValidationEnabled = isXssValidationEnabled;
   }
 
   @Override
   public Authentication attemptAuthentication(
       HttpServletRequest httpServletRequest,
       HttpServletResponse httpServletResponse
   ) throws IOException {
 
     String token = null;
     String authHeader = httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION);
     if (authHeader != null && authHeader.startsWith(BEARER_PREFIX)) {
       token = authHeader.substring(BEARER_PREFIX.length() + 1);
     }
 
     if (token == null) {
       Cookie cookie = WebUtils.getCookie(httpServletRequest, cookieName);
       if (cookie == null) {
         httpServletResponse.sendError(401);
         return null;
       }
       token = cookie.getValue();
     }
 
     try {
       String userClaim = JwtEncoder.getUserClaimFromToken(jwtEncodingKey, token);
       if (isXssValidationEnabled && XssValidator.isStringInvalid(userClaim)) {
         LOG.debug("Xss validation for user claim has been failed");
         httpServletResponse.sendError(401);
         return null;
       }
       User user = mapper.readValue(userClaim, User.class);
       Authentication auth = new UsernamePasswordAuthenticationToken(user, BEARER_PREFIX + " " + token);
       return getAuthenticationManager().authenticate(auth);
     } catch (Exception e) {
       httpServletResponse.sendError(401);
       return null;
     }
   }
 
   @Override
   protected void successfulAuthentication(
       HttpServletRequest request,
       HttpServletResponse response,
       FilterChain chain,
       Authentication authResult) throws IOException, ServletException {
 
     super.successfulAuthentication(request, response, chain, authResult);
     request.setAttribute(USER_CONTEXT_KEY, authResult.getPrincipal());
     chain.doFilter(request, response);
   }
 
 }